<?php
/**
 * CK 开发框架
 * User: Clake
 * Date: 15/6/21
 * Time: 00:58
 */

namespace CK\Util;


use CK\Core\Base;

/**
 * 加密解密类
 * Class Cipher
 *
 * @package CK\Util
 */
class Cipher extends Base{

    /**
     * @var Cipher
     */
    private static $_instance;

    public static function inst($key='ck_core') {
        if (!isset(self::$_instance)) {
            self::$_instance = new self($key);
        } else {
            if ($key !== self::$_instance->getSecureKey()) {
                self::$_instance->setSecureKey($key);
            }
        }
        return self::$_instance;
    }

    private $_secure_key;
    private $_openssl;
    private $iv;
//    private $_chipher_type = MCRYPT_RIJNDAEL_128;
    private $_openssl_chiper_type = 'AES-128-CBC';

    public function __construct($key) {
        $this->setSecureKey($key);
        $this->_openssl = version_compare(PHP_VERSION,'7.0.0','>=');
        if ($this->_openssl) {
//            $this->iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->_openssl_chiper_type));
            $this->iv = '0987654321abcdef';
        } else {
            $this->iv = '0987654321abcdef';
        }
    }

    /**
     * 得到当前加密类型
     * @return string
     */
    public function getChipherType() {
        return $this->_chipher_type;
    }

    /**
     * 设置加密类型
     * @param string $chipher_type
     */
    public function setChipherType($chipher_type) {
        $this->_chipher_type = $chipher_type;
    }

    /**
     * 加密一个字符串
     *
     * @param $input
     *
     * @return string
     */
    public function encrypt($input) {
        if ($this->_openssl) {
            $cipher_str = openssl_encrypt($input, $this->_openssl_chiper_type, $this->_secure_key,true, $this->iv);
        } else {
            $cipher_str = mcrypt_encrypt($this->_chipher_type, $this->_secure_key, $input, MCRYPT_MODE_ECB, $this->iv);
        }
        return base64url_encode($cipher_str);
    }

    /**
     * 解密一个字符串
     * @param $input
     *
     * @return string
     */
    public function decrypt($input) {
        if ($this->_openssl) {
            $cipher_str = openssl_decrypt(base64url_decode($input), $this->_openssl_chiper_type, $this->_secure_key,true, $this->iv);
        } else {
            $cipher_str = mcrypt_decrypt($this->_chipher_type, $this->_secure_key, base64url_decode($input), MCRYPT_MODE_ECB, $this->iv);
        }
        return trim($cipher_str);
    }
    /**
     * 得到当前加密密钥
     * @return string
     */
    public function getSecureKey() {
        return $this->_secure_key;
    }

    /**
     * 设置当前加密密钥
     * @param string $secure_key
     */
    public function setSecureKey($secure_key) {
        $this->_secure_key = hash('sha256',$secure_key);
    }

    public function setIv($iv) {
        $this->iv = $iv;
    }

    public function getIv() {
        return $this->iv;
    }

    public function hexToStr($hex){//十六进制转字符串
        $string="";
        for($i=0;$i<strlen($hex)-1;$i+=2)
            $string.=chr(hexdec($hex[$i].$hex[$i+1]));
        return  $string;
    }

    public function strToHex($string){//字符串转十六进制
        $hex="";
        $tmp="";
        for($i=0;$i<strlen($string);$i++)
        {
            $tmp = dechex(ord($string[$i]));
            $hex.= strlen($tmp) == 1 ? "0".$tmp : $tmp;
        }
        $hex=strtoupper($hex);
        return $hex;
    }

    /**
     * pkcs7补码
     * @param string $string  明文
     * @param int $blocksize Blocksize , 以 byte 为单位
     * @return String
     */
    private function addPkcs7Padding($string, $blocksize = 32) {
        $len = strlen($string); //取得字符串长度
        $pad = $blocksize - ($len % $blocksize); //取得补码的长度
        $string .= str_repeat(chr($pad), $pad); //用ASCII码为补码长度的字符， 补足最后一段
        return $string;
    }

    /**
     * 除去pkcs7 padding
     *
     * @param String 解密后的结果
     *
     * @return String
     */
    private function stripPkcs7Padding($string){
        $slast = ord(substr($string, -1));
        $slastc = chr($slast);

        if(preg_match("/$slastc{".$slast."}/", $string)){
            $string = substr($string, 0, strlen($string)-$slast);
            return $string;
        } else {
            return false;
        }
    }
}